package com.only4play.common.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.only4play.json.mapper.CustomObjectMapper;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author liyuncong
 * @version 1.0
 * @file HttpRequestUtils
 * @brief http rest 请求工具
 * @details http rest 请求工具
 * @date 2024-03-14
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2024-03-14               liyuncong          Created
 */
public class HttpRequestUtils {

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    public HttpRequestUtils() {
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
    }

    public HttpRequestUtils(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
        objectMapper = new ObjectMapper();
    }

    public HttpRequestUtils(ObjectMapper objectMapper) {
        restTemplate = new RestTemplate();
        this.objectMapper = objectMapper;
    }

    public HttpRequestUtils(RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
    }

    public <T> ResponseEntity<T> execute(
        String baseUrl,
        HttpMethod method,
        Map<String, Object> headParamMap,
        Map<String, Object> urlParamMap,
        Object requestObj,
        Class<T> returnClass
    ) {
        HttpHeaders requestHeaders = null;
        if (!CollectionUtils.isEmpty(headParamMap)) {
            requestHeaders = new HttpHeaders();
            for (String headerName : headParamMap.keySet()) {
                requestHeaders.add(headerName, String.valueOf(headParamMap.get(headerName)));
            }
        }

        StringBuilder urlBuilder = new StringBuilder(baseUrl);
        if (!CollectionUtils.isEmpty(urlParamMap)) {
            urlBuilder.append("?");
            for (String param : urlParamMap.keySet()) {
                String encode = String.valueOf(urlParamMap.get(param));
                urlBuilder.append(param).append("=").append(encode).append("&");
            }
            urlBuilder.deleteCharAt(urlBuilder.length() - 1);
        }

        HttpEntity<Object> requestEntity = new HttpEntity<>(requestObj, requestHeaders);

        return restTemplate.exchange(urlBuilder.toString(), method, requestEntity, returnClass);
    }

    public <T> ResponseEntity<T> doGet(String baseUrl, Map<String, Object> urlParamMap, Class<T> returnClass) {
        return doGet(baseUrl, null, urlParamMap, returnClass);
    }

    public <T> ResponseEntity<T> doGet(String baseUrl, Map<String, Object> headParamMap, Map<String, Object> urlParamMap, Class<T> returnClass) {
        return execute(baseUrl, HttpMethod.GET, headParamMap, urlParamMap, null, returnClass);
    }

    public <T> ResponseEntity<T> doPost(String baseUrl, Object requestObj, Class<T> returnClass) {
        return doPost(baseUrl, null, requestObj, returnClass);
    }

    public <T> ResponseEntity<T> doPost(String baseUrl, Map<String, Object> headParamMap, Object requestObj, Class<T> returnClass) {
        return doPost(baseUrl, headParamMap, null, requestObj, returnClass);
    }

    public <T> ResponseEntity<T> doPost(String baseUrl, Map<String, Object> headParamMap, Map<String, Object> urlParamMap, Object requestObj, Class<T> returnClass) {
        return execute(baseUrl, HttpMethod.POST, headParamMap, urlParamMap, requestObj, returnClass);
    }

    public <T> ResponseEntity<T> doPost(String baseUrl, MediaType mediaType, Map<String, Object> headParamMap, Object requestObj, Class<T> returnClass) {
        if (headParamMap == null) {
            headParamMap = new HashMap<>();
        }
        headParamMap.put(HttpHeaders.CONTENT_TYPE, mediaType.toString());
        return execute(baseUrl, HttpMethod.POST, headParamMap, null, requestObj, returnClass);
    }

    public <T> ResponseEntity<T> doFormPost(String baseUrl, Map<String, Object> headParamMap, MultiValueMap<String, Object> requestObj, Class<T> returnClass) {
        return doPost(baseUrl, MediaType.APPLICATION_FORM_URLENCODED, headParamMap, requestObj, returnClass);
    }

    public <T> ResponseEntity<T> doJsonPost(String baseUrl, Map<String, Object> headParamMap, Class<T> returnClass, Object requestObj) {
        return doPost(baseUrl, MediaType.APPLICATION_JSON, headParamMap, requestObj, returnClass);
    }
}
